﻿using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Windows.Interop;

namespace WgpgCore
{
    public static class Utils
    {
        public static String GetTempFileName()
        {
            String tmpPath = Path.GetTempPath();
            return Path.Combine(tmpPath, Guid.NewGuid() + ".wgpg");
        }

        public static String GetApplicationDirectory()
        {
            return Path.GetDirectoryName(Assembly.GetAssembly(typeof(Utils)).CodeBase);
        }

        public static String GetFingerPrintBeautified(String fingerPrint)
        {
            if (fingerPrint == null)
                return null;

            if (fingerPrint.Length == 0 || (fingerPrint.Length % 4 != 0))
                return fingerPrint;

            StringBuilder bld = new StringBuilder(2 * fingerPrint.Length);
            for (Int32 i = 0; i < fingerPrint.Length; ++i)
            {
                if (i != 0 && (i % 4 == 0))
                    bld.Append(' ');
                bld.Append(fingerPrint[i]);
            }
            return bld.ToString();
        }

        public static String FindGpgPath()
        {
            const String gpgExe = @"GNU\GnuPG\gpg.exe";

            String path = null;

            path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), gpgExe);
            if (File.Exists(path))
                return path;

            path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), gpgExe);
            if (File.Exists(path))
                return path;

            return null;
        }

        public static Boolean IsValidPath(String path)
        {
            try
            {
                new FileInfo(path);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Reads data from a stream until the end is reached. The
        /// data is returned as a byte array. An IOException is
        /// thrown if any of the underlying IO calls fail.
        /// http://www.yoda.arachsys.com/csharp/readbinary.html
        /// </summary>
        /// <param name="stream">The stream to read data from</param>
        /// <param name="initialLength">The initial buffer length</param>
        public static Byte[] ReadFully(Stream stream, Int32 initialLength)
        {
            // If we've been passed an unhelpful initial length, just
            // use 32K.
            if (initialLength < 1)
                initialLength = 32768;

            Byte[] buffer = new Byte[initialLength];
            Int32 read = 0;

            Int32 chunk;
            while ((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0)
            {
                read += chunk;

                // If we've reached the end of our buffer, check to see if there's
                // any more information
                if (read == buffer.Length)
                {
                    Int32 nextByte = stream.ReadByte();

                    // End of stream? If so, we're done
                    if (nextByte == -1)
                        return buffer;

                    // Nope. Resize the buffer, put in the byte we've just
                    // read, and continue
                    Byte[] newBuffer = new Byte[buffer.Length * 2];
                    Array.Copy(buffer, newBuffer, buffer.Length);
                    newBuffer[read] = (Byte)nextByte;
                    buffer = newBuffer;
                    read++;
                }
            }

            // Buffer is now too big. Shrink it.
            Byte[] ret = new Byte[read];
            Array.Copy(buffer, ret, read);
            return ret;
        }

        #region RemoveIcon

        private const Int32 GWL_EXSTYLE = -20;
        private const Int32 WS_EX_DLGMODALFRAME = 0x0001;
        private const Int32 SWP_NOSIZE = 0x0001;
        private const Int32 SWP_NOMOVE = 0x0002;
        private const Int32 SWP_NOZORDER = 0x0004;
        private const Int32 SWP_FRAMECHANGED = 0x0020;

        public static void RemoveIcon(Window window)
        {
            // Get this window's handle
            IntPtr hwnd = new WindowInteropHelper(window).Handle;

            // Change the extended window style to not show a window icon
            Int32 extendedStyle = NativeMethods.GetWindowLong(hwnd, GWL_EXSTYLE);
            NativeMethods.SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);

            // Update the window's non-client area to reflect the changes
            NativeMethods.SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
        }

        #endregion RemoveIcon
    }
}
